#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <getopt.h>

#include "../error.h"
#include "../main.h"
#include "../util.h"
#include "try-logout.h" 
#include "../action/onlineinfo.h"
#include "../action/logout.h"

_Noreturn void verb_try_logout_usage(FILE *restrict out) {
    fputs("Usage: " PROGRAM_NAME " try-logout [OPTIONS]\n", out);
    fputs("Try to log out the network.\n", out);
    fputs("Host is required.\n", out);
    fputs("\n", out);
    fputs("Options:\n", out);
    fputs("  -h, --help                 display this help and exit\n", out);
    fputs("\n", out);
    fputs("Exit status:\n", out);
    fputs(" 0  if logged out successfully\n", out);
    fputs(" 1  if network is already logged out\n", out);
    fputs(" 2  if logged out failed\n", out);
    fputs(" 3  if failed to fetch online info\n", out);
    fputs(" 4  if failed to connect to the network\n", out);
    fputs(" 5  if other error happended\n", out);
    exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}

int verb_try_logout(const int argc, char* const* argv) {
    int lose = 0;
    static struct option long_options[] = {
        {"help",      no_argument,        NULL, 'h' },
        {0,           0,                  0,     0 }
    };
    
    while (1) {
        int c = getopt_long(argc, argv, "h", long_options, NULL);

        if (c == -1) {
            break;
        }

        switch (c) {
            case 'h':
                verb_try_logout_usage(stdout);
                break;

            default:
                lose = 1;
                break;
        }
    }

    if (lose) {
        verb_try_logout_usage(stderr);
        return EXIT_FAILURE;
    }
    
    if (optind < argc) {
        error(0, 0, "Too many arguments.\n");
        verb_try_logout_usage(stderr);
        exit(EXIT_FAILURE);
    }
    
    if (GLOBAL_ARGS.portal_host == NULL) {
        error(0, 0, "No host provided.");
        exit(EXIT_FAILURE);
    }
    
    int wait_max = 3;
    action_onlineinfo_result onlineinfo_result;
    for (int i = 0; i < wait_max; i++) {
        if (GLOBAL_ARGS.verbose_level >= 1) {
            fprintf(stderr, "Fetch online infomation attempt: %d\n", i + 1);
        }
        
        onlineinfo_result = action_onlineinfo(
            GLOBAL_ARGS.bind_interface,
            GLOBAL_ARGS.portal_host,
            NULL
        );
        
        if (onlineinfo_result.status == ACTION_FETCHING_FAILURE) {
            return 4;
        }
        
        if (onlineinfo_result.status == ACTION_PARSE_FAILURE) {
            return 5;
        }
        
        if (onlineinfo_result.return_status == SUCCESS) {
            if (GLOBAL_ARGS.verbose_level >= 2) {
                fprintf(stderr, "Status: success\n");
                fprintf(stderr, "UserIndex: %s\n", onlineinfo_result.user_index);
            }
            break;
        } else if (onlineinfo_result.return_status == FAILED) {
            if (GLOBAL_ARGS.verbose_level >= 2) {
                fprintf(stderr, "Status: failed\n");
                fprintf(stderr, "Message: %s\n", onlineinfo_result.message);
            }
            if (strstr(onlineinfo_result.message, "用户可能已经下线") != NULL) {
                return 1;
            }
            break;
        } else if (onlineinfo_result.return_status == WAIT) {
            if (GLOBAL_ARGS.verbose_level >= 2) {
                fprintf(stderr, "Status: wait\n");
                fprintf(stderr, "Message: %s\n", onlineinfo_result.message);
            }
            wait_max = 15;
            sleep(1);
            continue;
        }
        
        if (i == wait_max - 1) {
            // Failed!
            return 3;
        }
    }
    
    action_logout_result logout_result = action_logout(
        GLOBAL_ARGS.bind_interface,
        GLOBAL_ARGS.portal_host,
        GLOBAL_ARGS.portal_search,
        onlineinfo_result.user_index
    );
    
    switch (logout_result.status) {
        case ACTION_LOGOUT_SUCCESSFULLY:
            return 0;
        case ACTION_LOGOUT_FAILED:
            printf("Failed, message: %s\n", logout_result.message);
            return 2;
        case ACTION_FETCHING_FAILED:
            return 4;
        case ACTION_LOGOUT_PARSING_FAILED:
            return 5;
        default:
            assert(0);
            exit(1);
            break;
    }
}
